/*
 * Created on February 18, 2013 7:43 PM
 * 
 */
package sembr.dao.reader;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import sembr.entities.*;
/**
 *
 * @author adriano
 */
public class XmlFileReader 
{
    private String path;
    private DocumentBuilderFactory dbFactory;
    private DocumentBuilder dBuilder;
    private Document doc;

    public XmlFileReader(String path)
    {
        dbFactory = DocumentBuilderFactory.newInstance();
        
        try 
        {
            dBuilder = dbFactory.newDocumentBuilder();
        } 
        catch (ParserConfigurationException ex) 
        {
            Logger.getLogger(XmlFileReader.class.getName()).log(Level.SEVERE, null, ex);
        } 
        
        setPath(path);
    }
    
    /**
     * @return the path
     */
    public String getPath() 
    {
        return path;
    }

    /**
     * @param path the path to set
     */
    private void setPath(String path) 
    {
        this.path = path;
    }
    
    public SimulationSetup getSetup()
    {
        parseXmlFile(getPath() + "/pre_processing/setup.xml");
        
        SimulationSetup setup = new SimulationSetup();
        
        setup.setDomain(getDomain());
        setup.setSource(getSource());
        setup.setField(getField());    
        setup.setDieletrics(getDieletrics());
        
        return setup;
    }
    
    private Map<String, Double> getDieletrics()
    {
        Map<String, Double> dieletrics = new HashMap<>();
        
        NodeList nodeList = doc.getElementsByTagName("dieletrics").item(0).getChildNodes();
        
        for (int i = 0; i < nodeList.getLength(); i++)
        {
            Node item = nodeList.item(i);
            dieletrics.put(item.getNodeName(), Double.valueOf(item.getTextContent()));
        }  
        
        return dieletrics;
    }
    
    public ProjectSettings getProjectSettings()
    {
        parseXmlFile(getPath() +"/project_settings.xml");
        
        String projectDirectory = doc.getElementsByTagName("project_directory").item(0).getTextContent();
        String movieName =  doc.getElementsByTagName("movie_name").item(0).getTextContent(); 
        Boolean isMovie2D =  Boolean.valueOf(doc.getElementsByTagName("is_movie2d").item(0).getTextContent());
        Boolean isMovie3D =  Boolean.valueOf(doc.getElementsByTagName("is_movie3d").item(0).getTextContent());
        Boolean hasSource =  Boolean.valueOf(doc.getElementsByTagName("has_source").item(0).getTextContent());
        Boolean isFieldFixedTime =  Boolean.valueOf(doc.getElementsByTagName("is_fixed_field").item(0).getTextContent());
        Boolean isPreProcessing = Boolean.valueOf(doc.getElementsByTagName("is_pre_processing").item(0).getTextContent());
        Boolean isPostProcessing = Boolean.valueOf(doc.getElementsByTagName("is_post_processing").item(0).getTextContent());
        String axisDirection = doc.getElementsByTagName("axis_direction").item(0).getTextContent();
        
        double fieldRange[] = null;
        
        if (!"".equals(doc.getElementsByTagName("initial_range").item(0).getTextContent()) &&
           (!"".equals(doc.getElementsByTagName("final_range").item(0).getTextContent())))
        {
            fieldRange = new double[2];
            fieldRange[0] = Double.valueOf(doc.getElementsByTagName("initial_range").item(0).getTextContent()).doubleValue();       
            fieldRange[1] = Double.valueOf(doc.getElementsByTagName("final_range").item(0).getTextContent()).doubleValue();
        }
                
        ProjectSettings settings = new ProjectSettings();
        settings.setProjectDirectory(projectDirectory); 
        settings.setMovieName(movieName);
        settings.setIsMovie2D(isMovie2D);
        settings.setIsMovie3D(isMovie3D);
        settings.setHasSource(hasSource);
        settings.setIsFieldAtFixedTime(isFieldFixedTime);
        settings.setIsPreprocessing(isPreProcessing);
        settings.setIsPostProcessing(isPostProcessing);
        settings.setAxisDirection(axisDirection);
        
        if (getImageFileNames().isEmpty())
            settings.setPostProcessingImageFiles(null);
        else
            settings.setPostProcessingImageFiles(getImageFileNames());
            
       settings.setFieldRange(fieldRange);
        
        return settings;
    }
    
    private ArrayList<String> getImageFileNames()
    {
        ArrayList<String> imageFileNames = new ArrayList<>();
        NodeList childNodes = doc.getElementsByTagName("image_file_names").item(0).getChildNodes();
        
        for(int i = 0; i < childNodes.getLength(); i++)
        {
            Node item = childNodes.item(i);
            imageFileNames.add(item.getTextContent());
        }
        
        return imageFileNames;
    }
    
    private ComputacionalDomain getDomain()
    {
        double coordXInitial = Double.valueOf(doc.getElementsByTagName("xi").item(0).getTextContent()).doubleValue();
        double coordXFinal = Double.valueOf(doc.getElementsByTagName("xf").item(0).getTextContent()).doubleValue();
        double coordYInitial = Double.valueOf(doc.getElementsByTagName("yi").item(0).getTextContent()).doubleValue();
        double coordYFinal = Double.valueOf(doc.getElementsByTagName("yf").item(0).getTextContent()).doubleValue();
        double coordZInitial = Double.valueOf(doc.getElementsByTagName("zi").item(0).getTextContent()).doubleValue();
        double coordZFinal = Double.valueOf(doc.getElementsByTagName("zf").item(0).getTextContent()).doubleValue();
        
        double xExtension = Double.valueOf(doc.getElementsByTagName("x_extension").item(0).getTextContent()).doubleValue();
        double yExtension = Double.valueOf(doc.getElementsByTagName("y_extension").item(0).getTextContent()).doubleValue();
        double zExtension = Double.valueOf(doc.getElementsByTagName("z_extension").item(0).getTextContent()).doubleValue();
       
        double pmlThickness = Double.valueOf(doc.getElementsByTagName("pml_thickness").item(0).getTextContent()).doubleValue();
        double resolution = Double.valueOf(doc.getElementsByTagName("resolution").item(0).getTextContent()).doubleValue();
                
        ComputacionalDomain domain = new ComputacionalDomain();
        domain.setCoordXInitial(coordXInitial);
        domain.setCoordXFinal(coordXFinal);
        domain.setCoordYInitial(coordYInitial);
        domain.setCoordYFinal(coordYFinal);
        domain.setCoordZInitial(coordZInitial);
        domain.setCoordZFinal(coordZFinal);
        domain.setXExtension(xExtension);
        domain.setYExtension(yExtension);
        domain.setZExtension(zExtension);
        domain.setPmlThickness(pmlThickness);
        domain.setResolution(resolution);
        
        return domain;
    }
    
    private Source getSource()
    {
        String type = doc.getElementsByTagName("type").item(0).getTextContent();
        double frequency = Double.valueOf(doc.getElementsByTagName("frequency").item(0).getTextContent()).doubleValue();
        double width = Double.valueOf(doc.getElementsByTagName("width").item(0).getTextContent()).doubleValue();
        int startTime = Integer.valueOf(doc.getElementsByTagName("start_time").item(0).getTextContent()).intValue();
        int endTime = Integer.valueOf(doc.getElementsByTagName("end_time").item(0).getTextContent()).intValue();
        
        double position[] = new double[3];
        position[0] = Double.valueOf(doc.getElementsByTagName("x").item(0).getTextContent()).doubleValue();
        position[1] = Double.valueOf(doc.getElementsByTagName("y").item(0).getTextContent()).doubleValue();
        position[2] = Double.valueOf(doc.getElementsByTagName("z").item(0).getTextContent()).doubleValue();
        
        Source source = new Source();
        source.setType(type); 
        source.setFrequency(frequency);
        source.setWidth(width);
        source.setStartTime(startTime);
        source.setEndTime(endTime);
        source.setPosition(position);
        
        return source;
    }
    
    private Field getField()
    {
        String fieldType = doc.getElementsByTagName("type").item(0).getTextContent();
        String direction = doc.getElementsByTagName("direction").item(0).getTextContent();
        
        double[] initialPosition = new double[3];        
        initialPosition[0] = Double.valueOf(doc.getElementsByTagName("xi").item(0).getTextContent()).doubleValue();
        initialPosition[1] = Double.valueOf(doc.getElementsByTagName("yi").item(0).getTextContent()).doubleValue();
        initialPosition[2] = Double.valueOf(doc.getElementsByTagName("zi").item(0).getTextContent()).doubleValue();
        
        double[] finalPosition = new double[3];
        finalPosition[0] = Double.valueOf(doc.getElementsByTagName("xf").item(0).getTextContent()).doubleValue();        
        finalPosition[1] = Double.valueOf(doc.getElementsByTagName("yf").item(0).getTextContent()).doubleValue();        
        finalPosition[2] = Double.valueOf(doc.getElementsByTagName("zf").item(0).getTextContent()).doubleValue();
        
        Field field = new Field();
        field.setFieldType(fieldType);
        field.setDirection(direction);
        field.setInitialPosition(initialPosition);
        field.setFinalPosition(finalPosition);
        
        return field;                
    }   
    
    private void parseXmlFile(String fileName)
    {
        File xmlFile = new File(fileName);       
        
        try 
        {
            doc = dBuilder.parse(xmlFile);
        } 
        catch (SAXException | IOException ex) 
        {
            Logger.getLogger(XmlFileReader.class.getName()).log(Level.SEVERE, null, ex);
        }
        doc.getDocumentElement().normalize();
    }
}
